home *** CD-ROM | disk | FTP | other *** search
- Turbo Pascal for DOS Tutorial
- by Glenn Grotzinger
- Part 21: Use of the BGI.
- copyright (c) 1995-6 by Glenn Grotzinger
-
- Here is a solution to the problem presented last time.
-
- program part20; uses dos;
-
- const
- oneminute = 273; { # of timer ticks that happens in 15 seconds }
-
- var
- saveint09, saveint1c: procedure;
- timecounter, keycounter: integer;
- achar: char;
- timeup: boolean;
-
- {$F+}
- procedure counttime; interrupt;
- begin
- inc(timecounter);
- if timecounter = oneminute then
- timeup := true;
- inline($9C);
- saveint1c;
- end;
-
- procedure countkeys; interrupt;
- begin
- inc(keycounter);
- inline($9C);
- saveint09;
- end;
-
- {$F-}
-
- begin
- timeup := false;
- timecounter := 0;
- keycounter := 0;
- getintvec($09, @saveint09);
- getintvec($1C, @saveint1C);
- setintvec($09, @countkeys);
- setintvec($1C, @counttime);
-
- while timeup = false do
- read(achar);
-
- setintvec($09, @saveint09);
- setintvec($1C, @saveint1C);
- writeln('There were ', keycounter div 2, ' keys pressed.');
- end.
-
-
- BGI Intro
- =========
- This part is basically about using the Borland Graphics Interface. It is
- not generally recommended to use it -- use assembler instead to make it a
- lot quicker, and smaller.... but due to demand, and the ability to use the
- BGI for basic graphics, we will talk about use of the BGI. For heavy use
- of graphics, assembler is indeed better....
-
- BGI loader
- ==========
- Here, I will describe how to make the BGI files functionally more useable
- than in their current state....Compile with looking for the external BGI
- files is fine, but will run into an annoyance quick, especially with a
- distributed utility...it is easier to have the EXE available with the BGI
- files binded to it than to make a user keep track of the BGI files....
-
- There is a utility available in TP called BINOBJ. The BGI files are video
- control files, while CHR files are font definition files. They both are
- usable in graphics as binary files...and that is what BINOBJ does...it
- converts binary files to OBJect files, which may be handled like described
- before. The proper usage of this utility is...
-
- BINOBJ <binary file name> <object file name> <internal procedure name>
-
- Here is a sample command-line. To convert VESA16.BGI to an OBJ, do this:
-
- BINOBJ VESA16.BGI VESA16.OBJ Vesa16driver
-
- Locate the BGI files that should be in your TP/BGI directory.
- You will need to copy them off to a separate directory.
-
- After you convert all BGI files like this, I recommend you write a unit
- to link the BGI files in -- optionally, if you need fonts, you may write
- a unit to link those in likewise. Be sure to define your proper external
- procedures like it needs to be done. Make use of meaningful
- names, as you will have to remember them to make use of the graphics set.
- For example, I call my unit bgivideo; for each procedure, I put the first
- 8 chars of the name of the file, and then driver for the BGI files. These
- function names will be easy to remember when we need to use them.
-
- Going into Graphics Mode
- ========================
- Now, hopefully you have your BGI video unit ready now, and sitting in
- whatever directory you use to place your pascal code. Now we will discuss
- about how to go into graphics mode using the BGI.
-
- Generally, going to graphics mode initially would require setting up the
- BGI unit you created, and then performing an autodetect on the graphics,
- followed by an init into graphics mode.
-
- Let us look at some sample code...
-
- program video_example_1;{1} uses graph, bgivideo;
-
- var
- graphicsdriver, graphicsmode: integer;
-
- procedure errormessage(driver: string);
- begin
- writeln('There was an error: ', grapherrormsg(graphresult), driver);
- halt(1);
- end;
-
- begin
- {2}if (registerbgidriver(@attdriver) < 0) then
- errormessage('ATT');
- if (registerbgidriver(@cgadriver) < 0) then
- errormessage('CGA');
- if (registerbgidriver(@egavgadriver) < 0) then
- errormessage('EGA/VGA');
- if (registerbgidriver(@hercdriver) < 0) then
- errormessage('Herc');
- if (registerbgidriver(@pc3270driver) < 0) then
- errormessage('PC 3270');
-
- {3}detectgraph(graphicsdriver, graphicsmode);
- graphicsdriver := Detect;
- {4}initgraph(graphicsdriver, graphicsmode, '');
- {5}if GraphResult <> grOk then
- begin
- writeln('Video error.');
- halt(1);
- end;
-
- {6}repeat
- putpixel(random(getmaxx), random(getmaxy), random(getmaxcolor));
- until keypressed;
- readln;
-
- {7}closegraph;
- end.
-
- This is basically a random pixel place system using the video mode in the
- recommended auto-detect. Let's go through a few of the features of the
- code, which were marked by {}'s.
-
- {1} As we see, the graph, and bgivideo units are used here. The graph
- unit is the basic function interface for the BGI system. We are familiar
- with bgivideo from earlier.
-
- {2} RegisterBGIDriver() must be called for any and all realistic
- possibilities. I recommend that only the ones listed really need to be
- checked. If the function is less than zero, then there is a problem.
- The errormessage function holds a function called grapherrormsg() which
- will output a direct error as to why things aren't working right.
-
- {3} detectgraph detects the graphics card. it takes integers represented
- by graphicsdriver, and graphicsmode....graphicsdriver will hold the
- recommended video type, and graphicsmode will hold the recommended video
- mode (it can be changed). This is why we registered all the drivers...it
- will use whichever one it needs, and ultimately, the program will work with
- all video modes.
-
- {4} initgraph() takes us into graphics mode. It is called basically as
- indicated in the program. the third param '', is for when we load the
- BGI files externally. To do that, do not include BGIVIDEO and provide
- a path to the BGI files....to get a full auto-detect capability, just
- make all the BGI files available....it is easier in the long run to have
- the BGI files combined in the exec.
-
- {5} For almost any graphics function, a variable called graphresult is
- changed. There are graphics mode constants, which will be covered later,
- which are in there representing different things. grok is the one which
- indicates that things are OK.
-
- {6} This is the real meat of the procedure. It keeps placing pixels of
- random position and color on the screen until a key is pressed. getmaxx
- is the maximum screen position on the x axis. getmaxy is the maximum screen
- position on the y axis. Graphics screens have the same kind of dimensional
- setup as the crt graphics screens do. The putpixel procedure takes a
- x, y coordinate, then a color...getmaxcolor is a constant that holds the
- maximum # of colors present in the current video mode.
-
- {7} Closegraph is pretty much self-explanatory. It shuts down graphics mode
- and takes us back to text.
-
- BGI Font Usage
- ==============
- The CHR files you saw, are font files, which have an ability to be used in
- graphics programs....
-
- These files can be converted to OBJs, and I recommend that you do so for
- purposes of using the fonts.....
-
- Here is a small example of loading and using fonts -- I'm not repeating
- the video load code, so I will omit that....
-
- program video_example; uses graph, bgivideo;
-
- var
- graphicsdriver, graphicsmode: integer;
- i: integer;
-
- {1} {$L GOTH.OBJ}
- procedure Gothfont; external;
-
- procedure errormessage(driver: string);
- begin
- writeln('There was an error: ', grapherrormsg(graphresult), driver);
- halt(1);
- end;
-
- begin
- { This is the video load code }
-
- {2} if registerbgifont(@gothfont) < 0 then
- errormessage('Script font');
-
- i := 100;
- {3} settextstyle(DefaultFont, HorizDir, 1);
- {4} setcolor(blue);
- {5} outtextxy(20, i, 'This is the DEFAULT font.');
- {6} inc(i, textheight('T')+2);
- readln;
- {7} cleardevice;
- settextstyle(Gothicfont, horizdir, 2);
- setcolor(green);
- outtextxy(20, i, 'This is the GOTHIC font.');
- readln;
- closegraph;
- end.
-
- This basically goes into graphic mode, and writes those two statements to
- the screen. We will go through the areas marked by {}'s..
-
- {1} This is exactly like I described before. This is how we load the CHR
- file to not make it separate. We do it exactly like the BGI files, and
- set them up as external OBJ files.
-
- {2} registerbgifont works exactly like registerbgidriver does...it registers
- the font into the program -- load fonts judiciously -- only if you need
- them.
-
- {3} settextstyle() changes the font, direction, and size....things can
- be written out either horizontally, or vertically. Fonts letters are 8X8
- pixels in size...so it is also possible to zoom the fonts...the third
- is the factor in which it may be done...a 2 in the third parameter makes the
- letters 16X16 pixels, and so on and so forth.
-
- {4} setcolor(blue) sets the foreground graphics draw color to blue.
-
- {5} outtextxy() puts out a text statement at coordinate x, y for graphics
- mode.
-
- {6} textheight is a function which guages the height in pixels of a text
- placed in the statement.
-
- Font file names
- ===============
- DefaultFont; TriplexFont; SmallFont; SanSerifFont; GothicFont; represent
- fonts.
- HorizDir; VertDir;
-
- A VERY QUICK overview of commands available from BGI
- ====================================================
- Due to the volume of commands available, all of them can not be sufficiently
- covered in the space of this document. Most if not all of them are
- straight-forward to use. Look at page 185 of the Turbo Pascal language
- guide for a list of all of the BGI commands.
-
- Conclusion
- ==========
- IMO, Borland made the BGI very hard to use. I have stumbled across many
- things that looked like bugs in their system (I couldn't use their included
- script font). Beyond that, it works OK for light-duty graphics. Anything
- beyond that truly needs assembler.
-
- There is enough knowledge here to set up and make use of BGI (not with-
- standing the basic commands in that list -- for example, rectangle....
- draws a rectangle....).
-
- As another side note, you may have noticed that executables you create
- using methods described here are large. Get a program such as PKLITE,
- or LZEXE, and compress it. They compress down about 45-55%, in my
- experience. Graphics programs using BGI seem to characteristically
- compile to be large.
-
- Practice Programming Problem #21
- ================================
- Make a program which will successively place rectangles on the screen in
- random colors. Since it is hard to illustrate what I'm wanting, given
- this medium, I will place the final executable, named part21.EXE in the
- file at Garbo. Cut and paste the document after you save this, please.
- Here are the basic stats behind the program:
-
- 1) Squares are used. use the rectangle() function. it takes for arguments,
- the coordinates of the upper left hand corner, and the lower right hand
- corner.
- 2) Each square drawn successively is one pixel larger than the previous....
- 3) Continually draw the squares until the user presses a key.
- 4) The colors are randomly determined.
-
- Look at the program to get an idea of what I am looking for. Also please
- send comments back to ggrotz@2sprint.net if it happens to not work on your
- system for no readily apparent reason. I need to get an idea of how well
- these sample video routines work.
-
- Next Time
- =========
- Things will be indeterminate. I will be covering object-oriented program-
- ming. As I have not set down and figured out how many parts object-oriented
- programming will take to cover, I do not know.
-
- E-mail ggrotz@2sprint.net and suggest anything that has to do with TP, which
- I may have not covered. If it sounds good, I will cover it!
-